package com.gitee.ly.ymorm;

import com.gitee.ly.ymorm.executor.*;
import com.gitee.ly.ymorm.executor.handler.RoutingStatementHandler;
import com.gitee.ly.ymorm.executor.handler.StatementHandler;
import com.gitee.ly.ymorm.log.YmOrmLog;
import com.gitee.ly.ymorm.log.YmOrmLogFactory;
import com.gitee.ly.ymorm.mapping.ParamMap;
import com.gitee.ly.ymorm.mapping.YmOrmStatement;
import com.gitee.ly.ymorm.plugin.Interceptor;
import com.gitee.ly.ymorm.plugin.InterceptorChain;
import com.gitee.ly.ymorm.session.ExecutorType;
import com.gitee.ly.ymorm.transaction.Transaction;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * YmOrmConfig
 *
 * @author ly
 **/
public class YmOrmConfig {
    private Class<? extends YmOrmLog> logImpl;
    private String logPrefix;
    private final Properties properties = new Properties();
    private YmOrmEnvironment environment;
    private final InterceptorChain interceptorChain = new InterceptorChain();
    private final ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
    private boolean cacheEnabled = true;
    private final Map<String, YmOrmStatement> statementMap = new HashMap<String, YmOrmStatement>();

    public void setYmOrmLogImpl(Class<? extends YmOrmLog> logImpl) {
        if (logImpl != null) {
            this.logImpl = logImpl;
            YmOrmLogFactory.useCustomLogging(this.logImpl);
        }
    }

    public String getLogPrefix() {
        return logPrefix;
    }

    public void setLogPrefix(String logPrefix) {
        this.logPrefix = logPrefix;
    }

    public void setDriver(String driver) {
        properties.setProperty("driver", driver);
    }

    public void setUrl(String url) {
        properties.setProperty("url", url);
    }

    public void setUsername(String username) {
        properties.setProperty("username", username);
    }

    public void setPassword(String password) {
        properties.setProperty("password", password);
    }

    public Properties getProperties() {
        return properties;
    }

    public void setMinIdle(int minIdle) {
        properties.setProperty("minIdle", String.valueOf(minIdle));
    }

    public void setMaxPoolSize(int maxPoolSize) {
        properties.setProperty("maxPoolSize", String.valueOf(maxPoolSize));
    }

    public void loadEnviroment(YmOrmEnvironment environment) {
        this.environment = environment;
    }

    public YmOrmEnvironment getEnvironment() {
        return environment;
    }

    public ExecutorType getDefaultExecutorType() {
        return defaultExecutorType;
    }

    public void setCacheEnabled(boolean cacheEnabled) {
        this.cacheEnabled = cacheEnabled;
    }

    public boolean isCacheEnabled() {
        return cacheEnabled;
    }

    public void addInterceptor(Interceptor interceptor) {
        interceptorChain.addInterceptor(interceptor);
    }

    public void loadStatement() {
        statementMap.put("111", new YmOrmStatement());
        statementMap.put("222", new YmOrmStatement());
    }

    public YmOrmStatement getStatement(String statementId) {
        return statementMap.get(statementId);
    }

    public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
        executorType = executorType == null ? defaultExecutorType : executorType;
        Executor executor;
        if (ExecutorType.BATCH == executorType) {
            executor = new BatchExecutor(this, transaction);
        } else if (ExecutorType.REUSE == executorType) {
            executor = new ReuseExecutor(this, transaction);
        } else {
            executor = new SimpleExecutor(this, transaction);
        }
        if (cacheEnabled) {
            executor = new CachingExecutor(executor);
        }
        return (Executor) interceptorChain.pluginAll(executor);
    }

    public StatementHandler newStatementHandler(Executor executor, YmOrmStatement ymOrmStatement, ParamMap paramMap) {
        StatementHandler statementHandler = new RoutingStatementHandler(executor, ymOrmStatement, paramMap, null);
        return (StatementHandler) interceptorChain.pluginAll(statementHandler);
    }
}
